/* Copyright (c) 2010-2020 Vadim Surov.
 */
package com.srv.client.widget;

import java.util.ArrayList;
import java.util.List;

import com.google.gwt.editor.client.Editor;
import com.google.gwt.editor.client.EditorError;
import com.google.gwt.editor.client.testing.MockEditorError;
import com.sencha.gxt.widget.core.client.button.TextButton;
import com.sencha.gxt.widget.core.client.container.VerticalLayoutContainer;
import com.sencha.gxt.widget.core.client.event.SelectEvent;
import com.sencha.gxt.widget.core.client.event.SelectEvent.SelectHandler;
import com.sencha.gxt.widget.core.client.form.TextArea;
import com.sencha.gxt.widget.core.client.form.Validator;
import com.sencha.gxt.widget.core.client.toolbar.ToolBar;
import com.srv.shared.Card;
import com.srv.shared.Control;
import com.google.gwt.xml.client.Document;
import com.google.gwt.xml.client.Element;
import com.google.gwt.xml.client.NodeList;
import com.google.gwt.xml.client.Text;
import com.google.gwt.xml.client.XMLParser;

public class CardSourcePanel extends VerticalLayoutContainer {

	private int floating = 0;
	private List<Control> controls = null;
	private boolean isSafeToClose = true;

	private ToolBar toolbar = new ToolBar();
	private TextArea source = new TextArea();

	public static native void copyFrom(String text) /*-{
    $wnd.window.clipboardData.setData('text', text);
    }-*/;	

	public CardSourcePanel() {
		super();
		
		source.setHeight(200);
		toolbar.setSpacing(2);

		final TextButton copyAllButton = new TextButton("Copy All"){{
			addSelectHandler(new SelectHandler() {
				@Override
				public void onSelect(SelectEvent event) {
					copyFrom(source.getValue());
				}
			});
		}};
		toolbar.add(copyAllButton);

		add(toolbar, new VerticalLayoutData(1, -1));
		add(source, new VerticalLayoutData(1, 1));

		source.addValidator(new Validator<String>(){

			@SuppressWarnings("serial")
			@Override
			public List<EditorError> validate(Editor<String> editor,
					String value) {
				final String result = parse();
				if (result==null) { 
					isSafeToClose = true;
					return null;
				} else {
					isSafeToClose = false;
					return new ArrayList<EditorError>() {{ 
						add(new MockEditorError() { 
							@Override
							public String getMessage() {
								return result;
							}
						}); 
					}};
				}
			}
		});
		
	}

	public String parse() {
		if (source.getValue()==null) {
			return "There is nothing to apply";
		}

		try {
			Document doc = XMLParser.parse(source.getValue());

			NodeList cardNodelist = doc.getElementsByTagName("card");

			if (cardNodelist.getLength()==1) {
				Element cardElement = (Element) cardNodelist.item(0);
				//String cardName = cardElement.getAttribute("name");
				String floatingString = cardElement.getAttribute("floating");
				NodeList controlNodelist = cardElement.getElementsByTagName("control");
				
				List<Control> newControl = new ArrayList<Control>();
				
				for (int j=0, n=controlNodelist.getLength(); j<n; j++) {

					Element controlElement = (Element)controlNodelist.item(j);
					String controlType = controlElement.getAttribute("type");
					String controlValue = controlElement.getAttribute("value");
					Text tt = (Text)controlElement.getFirstChild();
					String text = (tt==null)?"":tt.getData();
					newControl.add(new Control(controlType, controlValue, text));
				}
				floating = Integer.parseInt(floatingString);
				controls = newControl;
			} else {
				return "Cannot apply changes: Card not found";
			}

		} catch (Exception e) { //DOMParseException
			return e.getMessage();
		}
		return null;
	}	

	public void setValue(Card card) {
		floating = card.getFloating();
		controls = card.getControls();
		source.reset();
		source.setValue(card.getXML("").toString());
	}

	public boolean isSafeToClose() {
		return isSafeToClose;
	}

	public int getFloating() {
		return floating;
	}

	public List<Control> getControls() {
		return controls;
	}

	public void setSafeToClose(boolean isSafe) {
		isSafeToClose = isSafe;
	}
}
